package cn.xorange.commons.security.filter;

import cn.xorange.commons.security.constants.SecurityConstants;
import cn.xorange.commons.security.entity.ClaimsInfo;
import cn.xorange.commons.security.entity.SecurityUser;
import cn.xorange.commons.security.exception.SecurityErrorCode;
import cn.xorange.commons.security.utils.JwtUtils;
import cn.xorange.commons.utils.cache.ICacheService;
import cn.xorange.commons.utils.http.ServletUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * @author : yangjian
 * @date : 2023/11/28
 */
public class JwtAuthTokenFilter extends OncePerRequestFilter {

    @Resource
    FilterHandlerFactory filterFactory;
    @Resource
    ICacheService cacheService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String url = request.getRequestURI();
        if(SecurityConstants.URL_LOGOUT.equals(url)){
            chain.doFilter(request, response);
            return;
        }
        FilterHandler filterHandler = filterFactory.getFilterHandler(url);
        if(Objects.isNull(filterHandler) && SecurityConstants.URL_GET_TENANT.equals(url)){
            SecurityErrorCode errorCode = SecurityErrorCode.TENANT_ON_ERROR;
            ServletUtils.responseOut(response, errorCode.getStatus(), errorCode.getCode(), errorCode.getMsg(), null);
            return;
        }

        if(Objects.nonNull(filterHandler) && filterHandler.passToken()){
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken("",null,null);
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            filterHandler.handler(request,response);
            return;
        }

        String jwtToken = JwtUtils.getJwtToken(request, response);

        if(Objects.nonNull(jwtToken)){
            JwtUtils.validateToken(response, jwtToken);
            String sysType = JwtUtils.getAudience(jwtToken);
            ClaimsInfo claimsInfo = JwtUtils.getClaims(jwtToken);
            SecurityUser user = cacheService.getCacheObject(claimsInfo.tokenKey());
            if(Objects.isNull(user)){
                SecurityErrorCode errorCode = SecurityErrorCode.AUTH_TOKEN_UNAUTHORIZED;
                ServletUtils.responseOut(response, errorCode.getStatus(), errorCode.getCode(), errorCode.getMsg(), null);
            }
            claimsInfo.setUserId(user.getUserId());
            claimsInfo.setUsername(user.getUsername());
            claimsInfo.setIsAdmin(user.getIsAdmin());
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(claimsInfo.getUserId(),claimsInfo.tokenKey(),null);
            authenticationToken.setDetails(claimsInfo);
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            if(Objects.nonNull(filterHandler)){
                filterHandler.handler(request, response);
                return;
            }
        }
        //放行，让后面的过滤器去处理
        chain.doFilter(request, response);

    }


}
